/*
    该文件是 FreeModbus 主机协议栈在 FreeRtos 操作系统、STM32 硬件平台上的定时器适配实现，
    核心功能是为 Modbus 通信提供三类关键定时服务：T35 帧间隔检测、RS485 转换延迟、从机响应超时，
    是确保 Modbus 协议时序合规的核心模块。
*/

/* ----------------------- Platform includes --------------------------------*/
#include "port.h"  // 平台端口适配头文件（硬件相关定义、接口声明）

/* ----------------------- Modbus includes ----------------------------------*/
#include "mb.h"       // Modbus 核心头文件（通用类型、错误码）
#include "mb_m.h"     // Modbus 主机核心头文件（主机模式专用定义）
#include "mbport.h"   // Modbus 端口抽象层头文件（声明定时器接口函数）
#include "gd32f30x.h"

// 条件编译：仅当启用 Modbus 主机 RTU 或 ASCII 模式时，编译以下定时器适配代码
#if MB_MASTER_RTU_ENABLED > 0 || MB_MASTER_ASCII_ENABLED > 0

static USHORT usTim1Timerout50us;  // 定时器超时值（单位：50微秒），存储 T35 定时参数
//static void prvvTIMERExpiredISR(void);

/* ----------------------- Start implementation -----------------------------*/


BOOL xMBMasterPortTimersInit(USHORT usTimeOut50us)
{
    usTim1Timerout50us = usTimeOut50us;
    /* 使能定时器时钟；*/
    rcu_periph_clock_enable(RCU_TIMER3);
    /* 复位定时器；*/
    timer_deinit(TIMER3);
    timer_parameter_struct timerInitPara;
    timer_struct_para_init(&timerInitPara);
    /* 设置预分频器值；*/
    timerInitPara.prescaler = 5999;   // 频率120MHZ / 6000 = 20khz,对应周期50us
    /* 设置自动重装载值；*/
    timerInitPara.period = usTimeOut50us - 1;
    timer_init(TIMER3, &timerInitPara);
    /* 使能定时器中断和优先级；*/
    nvic_irq_enable(TIMER3_IRQn, 5, 0);
    return TRUE;
}


/**
 * @brief  启用 Modbus T35 定时器（帧间隔检测）
 */
void vMBMasterPortTimersT35Enable()
{
    /* 设置当前定时器模式为 T35（告知协议栈当前定时用途，不可修改）*/
    vMBMasterSetCurTimerMode(MB_TMODE_T35);
    timer_counter_value_config(TIMER3, 0);//清零定时器
    timer_autoreload_value_config(TIMER3, usTim1Timerout50us - 1);
    timer_interrupt_flag_clear(TIMER3, TIMER_INT_UP);//清除定时器更新中断
    timer_interrupt_enable(TIMER3, TIMER_INT_UP);//使能定时器更新中断
    timer_enable(TIMER3);//使能定时器
}

/**
 * @brief  启用 Modbus 转换延迟定时器（RS485 模式切换延迟）
 * @note   主机发送广播帧后，需等待一段时间再发送新帧（避免总线冲突），
 *         延迟时间由 mbconfig.h 中的 MB_MASTER_DELAY_MS_CONVERT 定义（默认 200ms）。
 * @param  无
 * @return 无
 */
void vMBMasterPortTimersConvertDelayEnable()
{
    /* 设置当前定时器模式为“转换延迟”（告知协议栈当前定时用途，不可修改）*/
    vMBMasterSetCurTimerMode(MB_TMODE_CONVERT_DELAY);
    timer_counter_value_config(TIMER3, 0);//清零定时器
    timer_interrupt_flag_clear(TIMER3, TIMER_INT_UP);//清除定时器更新中断
    timer_interrupt_enable(TIMER3, TIMER_INT_UP);//使能定时器更新中断
    // 重新配置重装载值 因为频率是20kHZ 所以200ms需要重 200*20 才可以
    timer_autoreload_value_config(TIMER3, MB_MASTER_DELAY_MS_CONVERT * 20 - 1);
    timer_enable(TIMER3);//使能定时器
}

/**
 * @brief  启用 Modbus 从机响应超时定时器
 * @note   主机发送非广播帧后，需等待从机响应，超过设定时间未响应则判定为“超时错误”，
 *         超时时间由 mbconfig.h 中的 MB_MASTER_TIMEOUT_MS_RESPOND 定义（默认 100ms）。
 * @param  无
 * @return 无
 */
void vMBMasterPortTimersRespondTimeoutEnable()
{
    /* 设置当前定时器模式为“响应超时”（告知协议栈当前定时用途，不可修改）*/
    vMBMasterSetCurTimerMode(MB_TMODE_RESPOND_TIMEOUT);

    timer_counter_value_config(TIMER3, 0);//清零定时器
    timer_interrupt_flag_clear(TIMER3, TIMER_INT_UP);//清除定时器更新中断
    timer_interrupt_enable(TIMER3, TIMER_INT_UP);//使能定时器更新中断
    timer_autoreload_value_config(TIMER3, MB_MASTER_TIMEOUT_MS_RESPOND * 20 - 1);
    timer_enable(TIMER3);//使能定时器
}

/**
 * @brief  禁用 Modbus 主机定时器
 * @note   停止定时器计数和中断，重置计数器，用于“定时未超时就完成操作”的场景（如正常接收完从机响应）。
 * @param  无
 * @return 无
 */
void vMBMasterPortTimersDisable()
{
    timer_counter_value_config(TIMER3, 0);//清零定时器
    timer_interrupt_flag_clear(TIMER3, TIMER_INT_UP);//清除定时器更新中断
    timer_interrupt_disable(TIMER3, TIMER_INT_UP);//禁用定时器更新中断
    timer_disable(TIMER3);//失能定时器
}

/**
 * @brief  Modbus 主机定时器超时中断核心处理函数
 * @note   定时器（TIM3）超时后触发此函数，清除中断标志，调用协议栈回调函数处理超时事件，
 *         同时管理“异常上下文标记”（告知协议栈当前处于 ISR 上下文）。
 * @param  无
 * @return 无
 */
void prvv_MASTERTIMERExpiredISR(void)

{
    BOOL bTaskWoken = FALSE;  // 任务唤醒标志（用于 RTOS 上下文切换，本实现未实际使用）

    // 检查定时器更新中断标志（确认是超时触发，且中断已使能）
    if (timer_interrupt_flag_get(TIMER3, TIMER_INT_FLAG_UP) == SET) {
        timer_interrupt_flag_clear(TIMER3, TIMER_INT_FLAG_UP);
        timer_counter_value_config(TIMER3, 0);
        pxMBMasterPortCBTimerExpired(); // 调用协议栈回调函数，通知超时事件（协议栈会根据当前模式处理）
    }
    // 触发 RTOS 上下文切换
    portEND_SWITCHING_ISR(bTaskWoken ? pdTRUE : pdFALSE);
}



#ifdef USE_MODBUS_MASTER
/**
* @brief  TIM3 定时器中断服务函数（硬件中断入口）
* @note   TIM3 超时的中断总入口，直接调用 Modbus 主机定时器的核心处理函数，
*         完成“硬件中断 → 协议栈超时处理”的衔接。
* @param  无
* @return 无
*/
void TIMER3_IRQHandler(void)
{
    prvv_MASTERTIMERExpiredISR();  // 跳转至 Modbus 定时器超时处理逻辑
}
#endif


#endif
